package com.xiaotu.spider.youku.pageprocessor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.xiaotu.common.exception.SpiderException;
import com.xiaotu.common.exception.SpiderExceptionCode;
import com.xiaotu.common.model.TVRecordModel;
import com.xiaotu.common.model.TVSetsPlotModel;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.KeywordEncode;
import com.xiaotu.common.util.PageUtils;
import com.xiaotu.common.util.RegexUtils;
import com.xiaotu.common.util.StringUtil;
import com.xiaotu.common.util.TVProcessUtils;
import com.xiaotu.spider.APageProcessor;

import net.sf.json.JSONObject;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.selector.Html;

/**
 * 爬取电视剧相关信息类
 */
@Component("YouKuPageProcessor")
@Scope("prototype")
public class YouKuPageProcessor extends APageProcessor
{
	
	@Override
	protected Request getStartRequest(JSONObject target)
	{
		return new Request("http://www.soku.com/search_video/q_"
				+ KeywordEncode.encode(target.getString("tvName")));
	}
	
	@Override
	public String getPageDataType(Page page)
	{
		String url = page.getUrl().toString();
		if (url.contains("http://www.soku.com/search_video/q_"))
			return Constants.PageDataType.SEARCH_LIST;
		if (url.contains("http://v.youku.com/v_show"))
			return Constants.PageDataType.TV_COMMENT;
		else if (url.contains("http://list.youku.com/show/module?id="))
			return Constants.PageDataType.TV_PLOTSET;
		else
			return Constants.PageDataType.TV_RECORD;
	}
	
	/**
	 * 设置已更新集次
	 * @param tvInfoMap
	 * @param divObj
	 */
	private TVProcessUtils.UpdateSetGetter getGetter(final List<String> divList)
	{
		return new TVProcessUtils.UpdateSetGetter()
		{
			@Override
			public String getUpdateSet(int idx)
			{
				
				String setStr = new Html(divList.get(idx))
						.xpath("//em[@class='updateNotice']/text()").get();
				if (StringUtils.isEmpty(setStr))
					return null;
				if(setStr.contains("更新至")){
					setStr = RegexUtils.regexSearch(
							"更新至" + RegexUtils.REGEX_INTEGER + "集", setStr);
				}
				if(setStr.contains("集全")){
					setStr = RegexUtils.regexSearch(RegexUtils.REGEX_INTEGER + "集全", setStr);
				}
				if (StringUtils.isEmpty(setStr))
					return null;
				return RegexUtils.regexSearch(RegexUtils.REGEX_INTEGER, setStr);
			}
		};
		
	}
	
	@Override
	public void process(Page page)
	{
		Map<String, Object> tvMap = page.getRequest().getExtras();
		switch (this.getPageDataType(page))
		{
			case Constants.PageDataType.SEARCH_LIST:
				this.searchListProcess(page, tvMap);
				break;
			case Constants.PageDataType.TV_COMMENT:
				this.tvCommentProcess(page, tvMap);
				break;
			case Constants.PageDataType.TV_RECORD:
				this.tvRecordProcess(page, tvMap);
				break;
			case Constants.PageDataType.TV_PLOTSET:
				this.tvSetProcess(page, tvMap);
				break;
			default:
				break;
		}
	}
	
	protected void searchListProcess(Page page, Map<String, Object> tvMap)
	{
		
		String contents = page.getHtml().toString().substring(page.getHtml().toString().indexOf("\"html\":\"")+8);
		if(StringUtil.isNotEmpty(contents)){
			int titlecount = contents.indexOf("\"})</script> ");
			contents = contents.substring(0, titlecount);
			contents =contents.replace("\\n", "").replace("\\t", "").replace("\\\"", "");
			List<String> reslabelList =new ArrayList<String>();
			System.out.println(contents.toString());
			List<String> labelLink = RegexUtils.regexSearchAll(
					"(?=<a class=sk-pack pack-vertical data-spm=dposter  target=_blank href=\"http://www.soku.com/search_video"
							+ "/\"https://v.youku.com/v_show/id_).*?(?=<span class=source><label>播放源:</label> 优酷</span>)",contents);
			if(StringUtil.isNotEmpty(labelLink)){
				for (String regexLink : labelLink) {
					String labelList = RegexUtils.regexSearch(
							"(?<=<a class=sk-pack pack-vertical data-spm=dposter  target=_blank href=\"http://www.soku.com/search_video"
									+ "/\"https://v.youku.com/v_show/id_).*?(?=.html)",regexLink);
					reslabelList.add(labelList);
				}
				Set<String> set = new HashSet<String>(reslabelList);
				Html hmtlContent = new Html(contents);
				List<String> divListAll = hmtlContent.xpath("//div[@class='sk-result-list']//div[@class='sk-mod']").all();
				Set<String> links = new HashSet<String>();
				List<String> linkLists = new ArrayList<String>();
				List<String> names = new ArrayList<String>();
				List<String> tvTypes = new ArrayList<String>();
				List<String> releasetimes = new ArrayList<String>();
				List<List<String>> actorsList = new ArrayList<List<String>>();
				for (String contentDetail : divListAll) {
					Html htmlDetail = new Html(contentDetail);
					if(!htmlDetail.toString().contains("播放源:</label> 优酷")){
						continue;
					}
					String link = htmlDetail.xpath("//div[@class='sk-mod']//div[@class='mod-main']//div[@class='mod-header']//h2").get();
					if(StringUtil.isEmpty(link)){
						continue;
					}
					if(link.contains("_show d_") && link.contains(".html")){
						String link1 = link.substring(link.indexOf("_show d_")+8, link.indexOf(".html"));
						for (String linkset : set) {
							if(linkset.contains("==")){
								linkset = linkset.replace("==", "");
							}
							if(link1.contains(linkset.toLowerCase()) || link1.contains(linkset.toUpperCase())){
								link1 = "http://v.youku.com/v_show/id_"+linkset+".html";
								links.add(link1);
							}
						}
					}
					if(link.contains("_show/id_") && link.contains(".html")){
						String link2 = link.substring(link.indexOf("_show/id_")+9, link.indexOf(".html"));
						for (String linkset : set) {
							if(linkset.contains("==")){
								linkset = linkset.replace("==", "");
							}
							if(link2.contains(linkset.toLowerCase()) || link2.contains(linkset.toUpperCase())){
								link2 = "http://v.youku.com/v_show/id_"+linkset+".html";
								links.add(link2);
							}
						}
					}
					if(link.contains("_show d_") && link.contains("=.html")){
						String link3 = link.substring(link.indexOf("_show d_")+8, link.indexOf("=.html")).replace("\"", "");
						for (String linkset : set) {
							if(linkset.contains("=")){
								linkset = linkset.replace("=", "");
							}
							if(!links.toString().contains(linkset)){
								if(link3.contains(linkset.toLowerCase()) || link3.contains(linkset.toUpperCase())){
									link3 = "http://v.youku.com/v_show/id_"+linkset+"==.html";
									links.add(link3);
								}
								
							}
						}
					}
					
					/*String tvname = htmlDetail.xpath("//div[@class='sk-mod']//div[@class='mod-main']"
					+ "//div[@class='mod-header']//h2//a/@title").get();*/
					String aTvname = htmlDetail.xpath("//div[@class='sk-mod']//div[@class='mod-main']"
							+ "//div[@class='mod-header']//h2//a").get();
					if(aTvname.contains("title") && aTvname.contains("href")){
						aTvname =aTvname.substring(aTvname.indexOf("title=")+6, aTvname.indexOf("href"));
						String tvname =aTvname.trim().replace("\"", "").replace(" ", "");
						names.add(tvname.toUpperCase());
					}
					String tvtype = htmlDetail.xpath("//div[@class='sk-mod']//div[@class='mod-main']"
							+ "//div[@class='mod-header']//span[@class='base-type']//text()").get();
					if(StringUtil.isNotEmpty(tvtype) && tvtype.equals("剧集")){
						tvtype = "电视剧";
					}
					tvTypes.add(tvtype);
					
					String releasetime = htmlDetail.xpath("//div[@class='sk-mod']//div[@class='mod-main']"
							+ "//div[@class='mod-header']//span[@class='spc-lv-1']//text()").get();	
					releasetimes.add(releasetime);
					
					
					List<String> actorsSpan = htmlDetail.xpath("//div[@class='sk-mod']//div[@class='mod-main']"
							+ "//div[@class='mod-info']//span[2]//a/text()").all();
					actorsList.add(actorsSpan);
					
				}
				
				if(names.size() !=links.size()){
					links.add(null);
				}
				linkLists.addAll(links);
				TVProcessUtils.addTVFromSearchList(page, tvMap, names, linkLists, tvTypes,
						actorsList, null, new TVProcessUtils.TVMatcher()
				{
					@Override
					protected boolean addTV(Page page,
							Map<String, Object> tvinfoMap, String name,
							String tvType, List<String> actors,
							List<String> directors, String link, int idx)
					{
						if (TVProcessUtils.tvMatched(tvinfoMap, name,
								TVProcessUtils.getTVType(tvType), actors,
								directors)
								/*&& getSiteName()
										.equals(new Html(divList.get(idx))
												.xpath("//div[@class='s_inform']/div[@class='s_play']/div[@class='pos']/div[@class='pos_sel']/div[@class='pos_area']/span/text()")
												.get())*/)
						{
							PageUtils.addTargetRequest(page, link, tvinfoMap,
									true);
							return true;
						}
						return false;
					}
				}, null);
			}
		}
		
	}
	
	protected String getSiteName()
	{
		return Constants.SiteName.YOUKU;
	}
	
	private void tvCommentProcess(Page page, Map<String, Object> tvMap){
		String link = page.getHtml().xpath("//code[@id='bpmodule-playpage-righttitle-code']//div[@class='tvinfo']//h2/a/@href").get();
		if(StringUtil.isNotEmpty(link)){
			PageUtils.addTargetRequest(page, link, tvMap,true);
		}
	}
	
	private void tvRecordProcess(Page page, Map<String, Object> tvMap)
	{
		String yugaop =page.getHtml().xpath("//div[@class='mod fix']//div[@class='p-base']//div[@class='p-play']//a/text()").get();
		if(yugaop.contains("预告片")){
			return;
		}
		String score = null, playcount = null, commcount = null, upcount = null,
				downcount = null,firstTime=null;
		
		if (page.getUrl().toString().contains("http://www.youku.com/show_page/")
				|| !page.getUrl().toString()
						.contains("http://www.soku.com/detail/show/"))
		{
			
			List<String> liList = page.getHtml()
					.xpath("//div[@class='p-base']/ul/li").all();
			
			for (String li : liList)
			{
				if (li.contains("评分："))
				{
					Html htmlScore = new Html(li);
					score = htmlScore.xpath("//span[@class='star-num']/text()")
							.toString().trim();;
				}
				if (li.contains("总播放数："))
				{
					playcount = li
							.substring(li.indexOf("：") + 1, li.lastIndexOf("<"))
							.replace(",", "");
				}
				if (li.contains("评论："))
				{
					commcount = li
							.substring(li.indexOf("：") + 1, li.lastIndexOf("<"))
							.replace(",", "");
				}
				if (li.contains("顶："))
				{
					upcount = li
							.substring(li.indexOf("：") + 1, li.lastIndexOf("<"))
							.replace(",", "");
				}
				if (li.contains("优酷上映："))
				{
					firstTime = li
							.substring(li.indexOf("</label>") + 8, li.lastIndexOf("</span>"))
							.replace(",", "");
				}
			}
			
			// youKuResourcePipelineModel.setDirectors(page.getHtml().xpath("//span[@class='director']/@title").all());
			if ("1".equals(tvMap.get("tvType")))
			{
				String id = RegexUtils.regexSearch(
						"showid:\"" + RegexUtils.REGEX_INTEGER + "\"",
						page.getHtml().toString());
				if (StringUtils.isNotEmpty(id))
				{
					PageUtils.addTargetRequest(page,
							"http://list.youku.com/show/module?id="
									+ RegexUtils.regexSearch(
											RegexUtils.REGEX_INTEGER, id)
									+ "&tab=point&cname=%E7%94%B5%E8%A7%86%E5%89%A7&callback=a",
							tvMap);// 分集梗概
				}
				
			}
			
		}
		else if (page.getUrl().toString()
				.contains("http://www.soku.com/detail/show/"))
		{
			// http://www.soku.com/detail/show/XMTQ3ODIw
			score = page.getHtml()
					.xpath("//body/div[@class='sk_container']/div[@class='layout_21']/div[@class='maincol']/div[@class='detailinfo']/div[@class='detail']/div[@class='T']/ul[@class='stats']/li/div[@class='rating']/em[@class='num']/text()")
					.toString();
			playcount = page.getHtml()
					.xpath("//body/div[@class='sk_container']/div[@class='layout_21']/div[@class='maincol']/div[@class='detailinfo']/div[@class='detail']/div[@class='T']/ul[@class='stats']/li/span/text()")
					.toString();
			commcount = page.getHtml()
					.xpath("//body/div[@class='sk_container']/div[@class='layout_21']/div[@class='maincol']/div[@class='detailinfo']/div[@class='detail']/div[@class='T']/ul[@class='stats']/li/span[2]/text()")
					.toString();
			String upAndDwcount = page.getHtml()
					.xpath("//body/div[@class='sk_container']/div[@class='layout_21']/div[@class='maincol']/div[@class='detailinfo']/div[@class='detail']/div[@class='T']/ul[@class='stats']/li/span[3]/text()")
					.toString();
			String[] upAndDw = upAndDwcount.split("\\/");
			upcount = upAndDw[0];
			downcount = upAndDw[1];
			score = StringUtil.getString(score);
			upcount = StringUtil.getString(upcount);
			downcount = StringUtil.getString(downcount);
		}
		
		if (StringUtils.isEmpty(score) && StringUtils.isEmpty(playcount)
				&& StringUtils.isEmpty(upcount)
				&& StringUtils.isEmpty(downcount)
				&& StringUtils.isEmpty(commcount))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		page.putField(TVRecordModel.class.getName(), new TVRecordModel(
				tvMap.get("tvid") + "", TVProcessUtils.getPageTVName(tvMap),
				Constants.SiteName.YOUKU, score, playcount, upcount, downcount,
				commcount, null, TVProcessUtils.getPageUpdateSet(tvMap),firstTime));
		
	}
	
	private void tvSetProcess(Page page, Map<String, Object> tvMap)
	{
		String setString = page.getRawText();
		if (StringUtils.isEmpty(setString))
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		if (setString.contains("REQUEST_NOT_ALLOW"))
			throw new SpiderException(SpiderExceptionCode.DataInvalideException,
					"statusCode:403");
		
		setString = setString.substring(14, setString.lastIndexOf(")"));
		JSONObject setsJSON = JSONObject.fromObject(setString);
		Html html = new Html(setsJSON.getString("html"));
		List<String> setList = html
				.xpath("//div[@class='item-title c555']/a/text()").all();
		List<String> setsPlotList = html
				.xpath("//div[@class='item-intro c999']/text()").all();
		if (setList == null || setsPlotList == null || setList.isEmpty()
				|| setsPlotList.isEmpty()
				|| setList.size() != setsPlotList.size())
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		
		List<TVSetsPlotModel> dataList = new ArrayList<TVSetsPlotModel>();
		for (int i = 0; i < setList.size(); i++)
		{
			if (StringUtil.isEmpty(setsPlotList.get(i)))
				continue;
			dataList.add(new TVSetsPlotModel(tvMap.get("tvid") + "",
					tvMap.get("tvName") + "", i + 1 + "", setsPlotList.get(i)));
		}
		if (dataList.isEmpty())
			// throw new SpiderException(
			// SpiderExceptionCode.DataInvalideException);
			return;
		page.putField(TVSetsPlotModel.class.getName() + "List", dataList);
	}
	
	@Override
	protected String getSpiderType()
	{
		return Constants.SpiderTaskType.TV_YOUKU;
	}
}
